import logging

from django.db import transaction
from django.shortcuts import render

# Create your views here.
from fdfs_client.client import get_tracker_conf, Fdfs_client
from rest_framework.decorators import action
from rest_framework.mixins import ListModelMixin, CreateModelMixin
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.status import HTTP_400_BAD_REQUEST, HTTP_500_INTERNAL_SERVER_ERROR, HTTP_404_NOT_FOUND
from rest_framework.viewsets import GenericViewSet, ModelViewSet, ReadOnlyModelViewSet

from DRFStudy_34_test.settings import alipay
from celery_tasks.email.tasks import send_mail_task
from shopping.models import Classification, Commodity, CommodityImg, ShoppingCart, Order, Payment
from shopping.serializers import ClassificationSerializer, ParentClassificationSerializer, CommoditySerializer, \
    ShoppingCartSerializer, OrderSerializer, PaymentSerializer


class ClassificationViewSet(GenericViewSet, ListModelMixin):
    queryset = Classification.objects.filter(is_delete=False)
    serializer_class = ClassificationSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        if self.action == 'list':
            return self.queryset.filter(parent__isnull=True)
        return self.queryset

    def get_serializer_class(self):
        if self.action == "list":
            return ParentClassificationSerializer
        return self.serializer_class

    @action(methods=['get'], detail=True)
    def commodity(self, request, pk):
        # 获取一级分类下的所有商品 服饰 短袖 长袖 长裤

        # 获取二级分类下的所有商品 服饰下面的短袖商品
        try:
            classification = self.get_queryset().get(id=pk)
        except Classification.DoesNotExist:
            return Response(status=HTTP_400_BAD_REQUEST)
        # 通过分类得到对应的商品
        # classification1应该是一个变量 可以是一级也可以是二级的
        # 设计默认查询一级分类下的所有商品
        classification_attr = 'classification1'
        # 获取分类名
        classification_name = classification.name
        # 判断是一级分类还是二级分类
        if classification.parent:
            classification_attr = "classification2"
            # 二级分类名要做拼接的操作 得到父级分类的名字拼接二级分类名
            # 服饰-短袖
            classification_name = f'{classification.prant.name}--{classification.name}'
        # classification_attr保存的是商品分类的管理器名称
        # classification.classification1
        # classification_attr当做是模型对象的属性
        # 得到了该分类下的所有商品
        data = getattr(classification, classification_attr).filter(is_delete=False, status=1)
        return Response({
            'classification': classification_name,
            "commodity": CommoditySerializer(data, many=True).data
        })


logger = logging.getLogger(__name__)
tracker_path = get_tracker_conf('utils/fastdfs/client.conf')
client = Fdfs_client(tracker_path)


class CommodityViewSet(ModelViewSet):
    queryset = Commodity.objects.filter(is_delete=False)
    serializer_class = CommoditySerializer
    permission_classes = [IsAuthenticated]

    def create(self, request, *args, **kwargs):
        # 获取用户传入的数据
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()  # 保存的商品数据

        # 保存商品图片数据
        files = request.FILES.getlist('file')
        # 通过循环迭代获取到每张商品图
        for file in files:
            # 如果有数据 则判断是否符合数据类型
            if file.content_type not in ("image/png", "image/jpeg"):
                return Response(status=HTTP_400_BAD_REQUEST)
            try:
                images_ext_name = file.name.split('.')[-1]
            except Exception as e:
                logger.info("图片拓展名异常：%s" % e)
                images_ext_name = "png"
            try:
                upload_res = client.upload_by_buffer(file.read(), file_ext_name=images_ext_name)
            except Exception as e:
                logger.error("图片上传异常：%s" % e)
                return Response(status=HTTP_500_INTERNAL_SERVER_ERROR)
            else:
                if upload_res.get('Status') != 'Upload successed.':
                    logger.warning("图片上传失败")
                    return Response(status=HTTP_500_INTERNAL_SERVER_ERROR)
                images_name = upload_res.get("Remote file_id").decode()

                CommodityImg.objects.create(src=images_name, commodity_id=serializer.data["id"])
        return Response(serializer.data)

    @action(methods=['get'], detail=False)
    def optimization(self, request):
        queryset = self.get_queryset().order_by('-comments').order_by('-create_time')
        return Response(self.get_serializer(queryset[:5], many=True).data)

    # 限制只能查看已经发布的商品
    def get_queryset(self):
        if self.action in ['list', 'retrieve']:
            return self.queryset.filter(status=1)
        return self.queryset


class ShoppingCartViewSet(ModelViewSet):
    queryset = ShoppingCart.objects.all()
    serializer_class = ShoppingCartSerializer
    permission_classes = [IsAuthenticated]

    # def get_queryset(self):
    #     return self.request.user.shoppingcart_set.all()

    def create(self, request, *args, **kwargs):
        request.POST._mutable = True
        request.data["user"] = request.user.id
        return ModelViewSet.create(self, request, *args, **kwargs)

    def update(self, request, *args, **kwargs):
        request.POST._mutable = True
        request.data["user"] = request.user.id
        return ModelViewSet.update(self, request, *args, **kwargs)


class OrderViewSet(ReadOnlyModelViewSet, CreateModelMixin):
    queryset = Order.objects.all()
    serializer_class = OrderSerializer
    permission_classes = [IsAuthenticated]

    # 限制只能对自己的账户订单做操作
    def get_queryset(self):
        return self.request.user.order_set.all()

    @action(methods=["put"], detail=False)
    def status(self, request):
        query_dict = request.query_params
        data = query_dict.dict()

        # 得到订单编号
        order_id = data.get("out_trade_no")
        # 支付宝交易号
        trade_no = data.get("trade_no")
        # 开启事务
        with transaction.atomic():
            # 创建保存点
            save_point = transaction.savepoint()
            try:
                Payment.objects.create(
                    order_id=order_id,
                    trade_id=trade_no

                )
                self.get_queryset().filter(order_id=order_id, status=1).update(status=2)
            except Exception as e:
                transaction.savepoint_rollback(save_point)
                return Response(status=HTTP_500_INTERNAL_SERVER_ERROR)
            else:
                transaction.savepoint_commit(save_point)
                for i in self.get_queryset().get(order_id=order_id).ordergoods_set.all():
                    # 得到订单中的每个商品信息 用于写在邮件里面
                    send_mail_task.delay(
                        i.order.user.email,
                        f"""
                        <h2>下单成功<h2>
                        <h3>您在[HAOKE商场]购买的{i.commodity.name}*{i.number}下单成功待发货中
                        """
                    )
            return Response({"order_id": order_id, "trade_id": trade_no})


class PaymentViewSet(ReadOnlyModelViewSet):
    queryset = Payment.objects.all()
    serializer_class = PaymentSerializer

    @action(methods=['get'], detail=True)
    def pay(self, request, pk):
        """
        得到支付宝的支付页面，返回给客户端让用户支付
        :param request:
        :param pk:
        :return:
        """
        try:
            order = Order.objects.get(order_id=pk, user=request.user, status=1)
        except Order.DoesNotExist:
            return Response(status=HTTP_404_NOT_FOUND)

        # 调用支付宝接口
        order_string = alipay.api_alipay_trade_page_pay(
            # 得到订单号
            out_trade_no=order.order_id,
            # 支付金额
            total_amount=str(order.total_amount),
            # 标题
            subject=f"HAOKE商城{order.order_id}",
            # 回调地址 前端的支付结果页面
            return_url="http://localhost:5173/order/success"
        )
        # 支付页面
        pay_url = "https://openapi-sandbox.dl.alipaydev.com/gateway.do?" + order_string
        return Response({"pay_url": pay_url})
